using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml;
using System.Linq;
using Urs.Data.Domain.Stores;

namespace Urs.Services.Stores
{
    public partial class GoodsSpecParser : IGoodsSpecParser
    {
        private readonly IGoodsSpecService _goodsSpecService;

        public GoodsSpecParser(IGoodsSpecService goodsSpecService)
        {
            this._goodsSpecService = goodsSpecService;
        }

        #region Goods spec

        public virtual IList<int> ParseGoodsSpecIds(string attributes)
        {
            var ids = new List<int>();
            if (String.IsNullOrEmpty(attributes))
                return ids;

            try
            {
                var xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(attributes);

                var nodeList1 = xmlDoc.SelectNodes(@"//Attributes/GoodsVariantAttribute");
                foreach (XmlNode node1 in nodeList1)
                {
                    if (node1.Attributes != null && node1.Attributes["ID"] != null)
                    {
                        string str1 = node1.Attributes["ID"].InnerText.Trim();
                        int id = 0;
                        if (int.TryParse(str1, out id))
                        {
                            ids.Add(id);
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                Debug.Write(exc.ToString());
            }
            return ids;
        }

        public virtual IList<GoodsSpecMapping> ParseGoodsSpecs(string attributes)
        {
            var paMapping = new List<GoodsSpecMapping>();
            var ids = ParseGoodsSpecIds(attributes);
            foreach (int id in ids)
            {
                var pva = _goodsSpecService.GetGoodsSpecMappingById(id);
                if (pva != null)
                {
                    paMapping.Add(pva);
                }
            }
            return paMapping;
        }

        public virtual IList<GoodsSpecMapping> ParseGoodsSpecs(int goodsId, string attributes)
        {
            if (String.IsNullOrEmpty(attributes))
                return new List<GoodsSpecMapping>();

            var list = new List<GoodsSpecMapping>();
            try
            {
                var ids = new List<int>();
                var xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(attributes);

                var nodeList = xmlDoc.SelectNodes(@"//Attributes/GoodsVariantAttribute/GoodsSpecValue/Value");
                foreach (XmlNode node1 in nodeList)
                {
                    string str1 = node1.InnerText.Trim();
                    int id = 0;
                    if (int.TryParse(str1, out id))
                    {
                        ids.Add(id);
                    }
                }

                foreach (var id in ids)
                {
                    var map = _goodsSpecService.GetGoodsSpecMapping(goodsId, id);
                    if (map != null)
                        list.Add(map);
                }
            }
            catch (Exception exc)
            {
                Debug.Write(exc.ToString());
            }
            return list;
        }

        public virtual IList<GoodsSpecValue> ParseGoodsSpecValues(string attributes)
        {
            var pvaValues = new List<GoodsSpecValue>();
            var paMapping = ParseGoodsSpecs(attributes);
            foreach (var mapping in paMapping)
            {
                var pvaValuesStr = ParseValues(attributes, mapping.Id);
                foreach (string pvaValueStr in pvaValuesStr)
                {
                    if (!String.IsNullOrEmpty(pvaValueStr))
                    {
                        int pvaValueId = 0;
                        if (int.TryParse(pvaValueStr, out pvaValueId))
                        {
                            var pvaValue = _goodsSpecService.GetGoodsSpecValueById(pvaValueId);
                            if (pvaValue != null)
                                pvaValues.Add(pvaValue);
                        }
                    }
                }
            }
            return pvaValues;
        }

        public virtual IList<string> ParseValues(string attributes, int goodsSpecMapId)
        {
            var selectedGoodsSpecValues = new List<string>();
            try
            {
                var xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(attributes);

                var nodeList1 = xmlDoc.SelectNodes(@"//Attributes/GoodsVariantAttribute");
                foreach (XmlNode node1 in nodeList1)
                {
                    if (node1.Attributes != null && node1.Attributes["ID"] != null)
                    {
                        string str1 = node1.Attributes["ID"].InnerText.Trim();
                        int id = 0;
                        if (int.TryParse(str1, out id))
                        {
                            if (id == goodsSpecMapId)
                            {
                                var nodeList2 = node1.SelectNodes(@"GoodsSpecValue/Value");
                                foreach (XmlNode node2 in nodeList2)
                                {
                                    string value = node2.InnerText.Trim();
                                    selectedGoodsSpecValues.Add(value);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                Debug.Write(exc.ToString());
            }
            return selectedGoodsSpecValues;
        }

        public virtual string AddGoodsSpec(string attributes, GoodsSpecMapping pva, string value)
        {
            string result = string.Empty;
            try
            {
                var xmlDoc = new XmlDocument();
                if (String.IsNullOrEmpty(attributes))
                {
                    var element1 = xmlDoc.CreateElement("Attributes");
                    xmlDoc.AppendChild(element1);
                }
                else
                {
                    xmlDoc.LoadXml(attributes);
                }
                var rootElement = (XmlElement)xmlDoc.SelectSingleNode(@"//Attributes");

                XmlElement pvaElement = null;
                var nodeList1 = xmlDoc.SelectNodes(@"//Attributes/GoodsVariantAttribute");
                foreach (XmlNode node1 in nodeList1)
                {
                    if (node1.Attributes != null && node1.Attributes["ID"] != null)
                    {
                        string str1 = node1.Attributes["ID"].InnerText.Trim();
                        int id = 0;
                        if (int.TryParse(str1, out id))
                        {
                            if (id == pva.Id)
                            {
                                pvaElement = (XmlElement)node1;
                                break;
                            }
                        }
                    }
                }

                if (pvaElement == null)
                {
                    pvaElement = xmlDoc.CreateElement("GoodsVariantAttribute");
                    pvaElement.SetAttribute("ID", pva.Id.ToString());
                    rootElement.AppendChild(pvaElement);
                }

                var pvavElement = xmlDoc.CreateElement("GoodsSpecValue");
                pvaElement.AppendChild(pvavElement);

                var pvavVElement = xmlDoc.CreateElement("Value");
                pvavVElement.InnerText = value;
                pvavElement.AppendChild(pvavVElement);

                result = xmlDoc.OuterXml;
            }
            catch (Exception exc)
            {
                Debug.Write(exc.ToString());
            }
            return result;
        }

        public virtual bool AreGoodsSpecsEqual(string attributes1, string attributes2)
        {
            bool attributesEqual = false;
            if (ParseGoodsSpecIds(attributes1).Count == ParseGoodsSpecIds(attributes2).Count)
            {
                var pva1Collection = ParseGoodsSpecs(attributes2);
                var pva2Collection = ParseGoodsSpecs(attributes1);

                var rightCount = 0;
                foreach (var pva1 in pva1Collection)
                {
                    var pva2 = pva2Collection.FirstOrDefault(q => q.GoodsSpecValueId == pva1.GoodsSpecValueId);
                    if (pva2 != null)
                        rightCount++;
                }
                if (rightCount == pva1Collection.Count)
                    attributesEqual = true;
            }

            return attributesEqual;
        }

        public virtual GoodsSpecCombination FindGoodsSpecCombination(Goods goods,
            string attributesXml)
        {
            if (goods == null)
                throw new ArgumentNullException("goods");

            var combinations = _goodsSpecService.GetAllGoodsSpecCombinations(goods.Id);
            if (combinations.Count == 0)
                return null;

            foreach (var combination in combinations)
            {
                bool attributesEqual = AreGoodsSpecsEqual(combination.AttributesXml, attributesXml);
                if (attributesEqual)
                    return combination;
            }

            return null;
        }

        #endregion

    }
}
